Skip to content

Conversation

danarmak
Copy link
Contributor

@danarmak danarmak commented Sep 2, 2025

This extends the fix in #650 to the tagged union strategy. I reported the issue in #682.

Without this, using include_subclasses with tagged_union and a generic parent class raises the error AttributeError: __subclasses__. Did you mean: '__subclasscheck__'?.

Note: I don't know whether to edit default_tag_generator to say return (typing.get_origin(typ) or typ).__name__. It doesn't break any tests, but I'm not sure if there are cases where it wouldn't be appropriate, or what else ought to be changed if this is. For now I left it as a tag_generator override at the callsite, but it would be better for users not to have to pass this. Please advise.

The tests don't pass for me locally on the main branch (regardless of my change), but the failure is in a test that doesn't use these strategies and all the tests passed when I rebased my fix on 25.1.1, so I hope I'm just confused about something unrelated. (The failure is tests/test_gen_dict.py::test_individual_overrides - assert 'Factory' not in "{'a': ('', ... '_b': None}")

(ETA: the tests now pass, see comments)

@danarmak danarmak force-pushed the fix-generics-with-tagged-union branch from 60feae8 to af4565d Compare September 2, 2025 18:44
@Tinche
Copy link
Member

Tinche commented Sep 2, 2025

Thanks, I'll take a look when I get some free cycles. Can you get me a more detailed error message on that flaky test in the meantime?

@danarmak
Copy link
Contributor Author

danarmak commented Sep 3, 2025

Here is the failing test output.

@Tinche
Copy link
Member

Tinche commented Sep 3, 2025

Cool, thanks. Can you rebase, I reworked those tests.

@danarmak danarmak force-pushed the fix-generics-with-tagged-union branch from af4565d to a198b33 Compare September 3, 2025 14:35
@danarmak
Copy link
Contributor Author

danarmak commented Sep 3, 2025

I rebased. All tests now pass.

@Tinche Tinche self-requested a review September 20, 2025 14:59
@Tinche
Copy link
Member

Tinche commented Sep 20, 2025

Looks great to me. I'm away from a computer until tomorrow, what happens if we don't substitute the tag generator?

@danarmak
Copy link
Contributor Author

danarmak commented Sep 23, 2025

Without substituting tag_generator, the test fails like this:

src/cattrs/strategies/_unions.py:58: in configure_tagged_union
src/cattrs/strategies/_unions.py:19: in default_tag_generator
    return typ.__name__
        typ        = tests.strategies.test_include_subclasses.test_parents_with_generics_tagged_union.<locals>.GenericParent[typing.Any]
/usr/lib/python3.9/typing.py:711: in __getattr__
    raise AttributeError(attr)
E   AttributeError: __name__

So it seems like a good idea to do this in the default tag generator, but like I said, I'm not sure if that approach means making similar changes in many more places. What code 'officially' supports generic types? Should all code support generic types and any code that breaks be fixed when we notice it? Should 'higher level' / user facing code apply get_origin once so internal functions won't have to do it every time, and what counts as user facing? Etc.

@Tinche
Copy link
Member

Tinche commented Sep 23, 2025

Got it. Hm, it only fails on 3.9 for me. I wouldn't change it globally, especially since in a few months 3.9 goes away.

@danarmak
Copy link
Contributor Author

You're right, I didn't realize that. I don't personally care about supporting python 3.9, so that's fine by me!

@Tinche
Copy link
Member

Tinche commented Sep 23, 2025

Cool. Thanks for the contribution!

@Tinche Tinche merged commit 64f6305 into python-attrs:main Sep 23, 2025
12 checks passed
@danarmak danarmak deleted the fix-generics-with-tagged-union branch September 24, 2025 20:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants